package cuongnh.project.japanesediary.vocabulary.ui.view;

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

import org.eclipse.core.databinding.DataBindingContext;
import org.eclipse.core.databinding.beans.BeansObservables;
import org.eclipse.core.databinding.observable.IChangeListener;
import org.eclipse.core.databinding.observable.map.IObservableMap;
import org.eclipse.core.databinding.observable.set.IObservableSet;
import org.eclipse.core.databinding.property.Properties;
import org.eclipse.jface.action.ContributionItem;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.IToolBarManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.databinding.viewers.ObservableMapLabelProvider;
import org.eclipse.jface.databinding.viewers.ObservableSetContentProvider;
import org.eclipse.jface.layout.TableColumnLayout;
import org.eclipse.jface.viewers.ColumnWeightData;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TableViewer;
import org.eclipse.jface.viewers.TableViewerColumn;
import org.eclipse.jface.viewers.Viewer;
import org.eclipse.jface.viewers.ViewerFilter;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableColumn;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.ISelectionListener;
import org.eclipse.ui.IWorkbenchActionConstants;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.forms.widgets.FormToolkit;
import org.eclipse.ui.internal.PluginActionContributionItem;
import org.eclipse.wb.swt.SWTResourceManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Scope;
import org.springframework.stereotype.Component;

import cuongnh.coreframework.ui.workbench.common.view.AutoUpdateView;
import cuongnh.project.japanesediary.vocabulary.common.CommonServices;
import cuongnh.project.japanesediary.vocabulary.common.CommonUtils;
import cuongnh.project.japanesediary.vocabulary.model.Category;
import cuongnh.project.japanesediary.vocabulary.model.Vocabulary;
import cuongnh.project.japanesediary.vocabulary.ui.common.composite.SearchComposite;

@Component("categoryVocabulariesView")
@Scope("prototype")
public class CategoryVocabulariesView extends AutoUpdateView implements
		ISelectionListener {
	private DataBindingContext m_bindingContext;

	public static final String ID = "cuongnh.project.japanesediary.vocabulary.ui.view.CategoryVocabulariesView"; //$NON-NLS-1$
	private TableViewer tblvVocabularies;

	private SearchComposite search;
	@Autowired
	private CommonServices commonServices;
	private Category selectedCategory;
	private Set<Vocabulary> categoryVocabularies;

	private final FormToolkit toolkit = new FormToolkit(Display.getCurrent());

	public CategoryVocabulariesView() {
	}

	/**
	 * Create contents of the view part.
	 * 
	 * @param parent
	 */
	@Override
	public void createPartControl(Composite parent) {
		Composite container = toolkit.createComposite(parent, SWT.NONE);
		container.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_WIDGET_BACKGROUND));
		toolkit.paintBordersFor(container);
		container.setLayout(new GridLayout(1, false));
		// Search control
		search = new SearchComposite(container);
		search.setBackground(SWTResourceManager
				.getColor(SWT.COLOR_WIDGET_BACKGROUND));
		search.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false, 1,
				1));

		// Separate composite to embed the table
		Composite tableComposite = new Composite(container, SWT.NONE);
		tableComposite.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1));

		tblvVocabularies = new TableViewer(tableComposite, SWT.BORDER
				| SWT.FULL_SELECTION | SWT.MULTI);
		Table tblVocabularies = tblvVocabularies.getTable();
		tblVocabularies.setHeaderVisible(true);
		tblVocabularies.setLinesVisible(true);
		tblVocabularies.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true,
				true, 1, 1));

		TableViewerColumn tbclvVocabulary = new TableViewerColumn(
				tblvVocabularies, SWT.NONE);
		TableColumn tblclmnVocabulary = tbclvVocabulary.getColumn();
		tblclmnVocabulary.setWidth(100);
		tblclmnVocabulary.setText("Vocabulary");

		TableViewerColumn tbclvFurigana = new TableViewerColumn(
				tblvVocabularies, SWT.NONE);
		TableColumn tblclmnFurigana = tbclvFurigana.getColumn();
		tblclmnFurigana.setWidth(100);
		tblclmnFurigana.setText("Furigana");

		TableViewerColumn tbclvHanviet = new TableViewerColumn(
				tblvVocabularies, SWT.NONE);
		TableColumn tblclmnHanviet = tbclvHanviet.getColumn();
		tblclmnHanviet.setWidth(100);
		tblclmnHanviet.setText("HAN-VIET");

		TableViewerColumn tbclvVnMeaning = new TableViewerColumn(
				tblvVocabularies, SWT.NONE);
		TableColumn tblclmnVnMeaning = tbclvVnMeaning.getColumn();
		tblclmnVnMeaning.setWidth(100);
		tblclmnVnMeaning.setText("Vietnamese meaning");
		CommonUtils.vocabulariesHookDoubleClickCommand(tblvVocabularies);

		TableViewerColumn tbclvEnMeaning = new TableViewerColumn(
				tblvVocabularies, SWT.NONE);
		TableColumn tblclmnEnMeaning = tbclvEnMeaning.getColumn();
		tblclmnEnMeaning.setWidth(100);
		tblclmnEnMeaning.setText("English meaning");
		CommonUtils.vocabulariesHookDoubleClickCommand(tblvVocabularies);

		// Specify column's width by a percentage
		TableColumnLayout tblColumnLayout = new TableColumnLayout();
		tblColumnLayout.setColumnData(tblclmnVocabulary, new ColumnWeightData(
				20, true));
		tblColumnLayout.setColumnData(tblclmnFurigana, new ColumnWeightData(15,
				true));
		tblColumnLayout.setColumnData(tblclmnHanviet, new ColumnWeightData(10,
				true));
		tblColumnLayout.setColumnData(tblclmnVnMeaning, new ColumnWeightData(
				25, true));
		tblColumnLayout.setColumnData(tblclmnEnMeaning, new ColumnWeightData(
				25, true));
		tableComposite.setLayout(tblColumnLayout);

		// Filter
		tblvVocabularies.addFilter(new ViewerFilter() {
			@Override
			public boolean select(Viewer viewer, Object parentElement,
					Object element) {
				Vocabulary vocabulary = (Vocabulary) element;
				String text = String.valueOf(search.observeText().getValue());
				if ((vocabulary.getVocabulary() != null && vocabulary
						.getVocabulary().toLowerCase()
						.contains(text.toLowerCase()))
						|| (vocabulary.getFurigana() != null && vocabulary
								.getFurigana().toLowerCase()
								.contains(text.toLowerCase()))
						|| (vocabulary.getVnMeaning() != null && vocabulary
								.getVnMeaning().toLowerCase()
								.contains(text.toLowerCase()))
						|| (vocabulary.getEnMeaning() != null && vocabulary
								.getEnMeaning().toLowerCase()
								.contains(text.toLowerCase()))) {					
					return true;
				}

				return false;
			}
			
			

		});

		search.observeText().addChangeListener(new IChangeListener() {
			@Override
			public void handleChange(
					org.eclipse.core.databinding.observable.ChangeEvent event) {
				tblvVocabularies.refresh();
			}
		});

		createActions();
		initializeToolBar();
		initializeMenu();
		this.hookContextMenu();
		CommonUtils.vocabulariesHookDoubleClickCommand(tblvVocabularies);
		this.setInterval(1);
		this.startAutoReload();
		// add this view as a selection listener to the workbench page
		getSite().getPage().addSelectionListener((ISelectionListener) this);
		initData();
		m_bindingContext = initDataBindings();

	}

	public void initData() {
		if (selectedCategory != null) {
			categoryVocabularies = commonServices.getCategoryDao()
					.getCategoryVocabularies(selectedCategory.getCategoryId());
		} else {
			categoryVocabularies = new HashSet<Vocabulary>();
		}
	}

	public void refresh() {
		if (selectedCategory != null) {
			categoryVocabularies.clear();
			categoryVocabularies.addAll(commonServices.getCategoryDao()
					.getCategoryVocabularies(selectedCategory.getCategoryId()));
			m_bindingContext.updateModels();
			tblvVocabularies.refresh();
		}
	}

	/**
	 * Create the actions.
	 */
	private void createActions() {
		// Create the actions
	}

	/**
	 * Initialize the toolbar.
	 */
	private void initializeToolBar() {
		IToolBarManager tbm = getViewSite().getActionBars().getToolBarManager();
	}

	/**
	 * Initialize the menu.
	 */
	private void initializeMenu() {
		IMenuManager manager = getViewSite().getActionBars().getMenuManager();
	}

	@Override
	public void setFocus() {
		// Set the focus
	}

	@Override
	public void update() {
		refresh();
	}

	@Override
	public void dispose() {
		// TODO Auto-generated method stub
		super.dispose();
	}

	@Override
	public void selectionChanged(IWorkbenchPart part, ISelection selection) {
		if (((StructuredSelection) selection).getFirstElement() != null) {
			if (((StructuredSelection) selection).getFirstElement() instanceof Category) {
				this.selectedCategory = (Category) ((StructuredSelection) selection)
						.getFirstElement();
				update();
			}
		}

	}

	public CommonServices getCommonServices() {
		return commonServices;
	}

	public Category getSelectedCategory() {
		return selectedCategory;
	}

	private void hookContextMenu() {
		MenuManager menuMgr = new MenuManager("#PopupMenu"); //$NON-NLS-1$
		menuMgr.setRemoveAllWhenShown(true);
		menuMgr.addMenuListener(new IMenuListener() {
			public void menuAboutToShow(IMenuManager manager) {
				CategoryVocabulariesView.this.fillContextMenu(manager);
			}
		});
		Menu menu = menuMgr.createContextMenu(tblvVocabularies.getControl());
		tblvVocabularies.getControl().setMenu(menu);
		getSite().registerContextMenu(menuMgr, tblvVocabularies);
	}

	private void fillContextMenu(IMenuManager manager) {
		IActionBars bars = getViewSite().getActionBars();

		ContributionItem item;
		for (int index = 0; index < bars.getToolBarManager().getItems().length; index++) {
			item = (ContributionItem) bars.getToolBarManager().getItems()[index];
			if (!item.isSeparator()) {
				manager.add(((PluginActionContributionItem) item).getAction());
			}

		}

		// Other plug-ins can contribute there actions here
		manager.add(new Separator(IWorkbenchActionConstants.MB_ADDITIONS));
	}

	protected DataBindingContext initDataBindings() {
		DataBindingContext bindingContext = new DataBindingContext();
		//
		ObservableSetContentProvider setContentProvider = new ObservableSetContentProvider();
		IObservableMap[] observeMaps = BeansObservables.observeMaps(
				setContentProvider.getKnownElements(), Vocabulary.class,
				new String[] { "vocabulary", "furigana", "hanviet",
						"vnMeaning", "enMeaning" });
		tblvVocabularies.setLabelProvider(new ObservableMapLabelProvider(
				observeMaps));
		tblvVocabularies.setContentProvider(setContentProvider);
		//
		IObservableSet selfSet = Properties.selfSet(Vocabulary.class).observe(
				categoryVocabularies);
		tblvVocabularies.setInput(selfSet);
		//
		return bindingContext;
	}

	public Set<Vocabulary> getSelectedVocabularies() {
		Set<Vocabulary> selectedVocabularies = new HashSet<Vocabulary>();
		StructuredSelection sel = (StructuredSelection) tblvVocabularies
				.getSelection();
		for (Iterator<Vocabulary> iter = sel.iterator(); iter.hasNext();) {
			selectedVocabularies.add(iter.next());
		}

		return selectedVocabularies;
	}

	public TableViewer getTblvVocabularies() {
		return tblvVocabularies;
	}
}
